{#include main fluid=true}
  
  {#script}
  // Build step dependency graph built with d3.js
  // Based on https://observablehq.com/@d3/mobile-patent-suits 
  
  const stepId = "{currentRequest.getParam('stepId')}";
  
  const nodes = [
  {#each info:buildMetrics.get.dependencyGraphs.get(currentRequest.getParam('stepId')).nodes}
    { id:"{it.stepId}", root:{#if it.stepId == currentRequest.getParam('stepId')}true{#else}false{/if}, simpleName:"{it.simpleName}", encodedId:"{it.encodedStepId}" },
  {/each}
  ];
  const links = [
  {#each info:buildMetrics.get.dependencyGraphs.get(currentRequest.getParam('stepId')).links}
    { source:"{it.source}", target:"{it.target}", type:"{it.type}" },
  {/each}
  ];
  
  {|
  const types = ['directDependency','directDependent','dependency'];
  const height = 600;
  const width = 1200;
  const color = d3.scaleOrdinal(types, d3.schemeCategory10);
  
  // Legend colors
  const legendDirectDependency = document.querySelector(".legend-direct-dependency");
  legendDirectDependency.style.color = color('directDependency');
  const legendDirectDependent = document.querySelector(".legend-direct-dependent");
  legendDirectDependent.style.color = color('directDependent');
  // const legendDependency = document.querySelector(".legend-dependency");
  // legendDependency.style.color = color('dependency');
  
  function linkArc(d) {
    const r = Math.hypot(d.target.x - d.source.x, d.target.y - d.source.y);
    return `
        M${d.source.x},${d.source.y}
        A${r},${r} 0 0,1 ${d.target.x},${d.target.y}
        `;
  }
  
  const simulation = d3.forceSimulation(nodes)
      .force("link", d3.forceLink(links).id(d => d.id).distance(function(d) {
        return d.source.id === stepId || d.type === 'directDependency' ? 125 : 255;
      }))
      .force("charge", d3.forceManyBody().strength(-400))
      .force("x", d3.forceX())
      .force("y", d3.forceY());
      
  function dragstart(event, d){
    // this line is needed, otherwise the simulation stops after few seconds
    if (!event.active) simulation.alphaTarget(0.3).restart();
    d.fx = d.x;
    d.fy = d.y;
  };
  
  function dragged(event, d) {
    d.fx = event.x;
    d.fy = event.y;
  }
  
  function dragended(event, d) {
    d.fx = event.x;
    d.fy = event.y;
  }
  
  const svg = d3.select("#buildStepDepGraph_area")
      .attr("viewBox", [-width / 3, -height / 3, width, height])
      .style("font", "11px sans-serif");

  svg.append("defs").selectAll("marker")
    .data(types)
    .join("marker")
      .attr("id", d => `arrow-${d}`)
      .attr("viewBox", "0 -5 10 10")
      .attr("refX", 15)
      .attr("refY", -0.5)
      .attr("markerWidth", 6)
      .attr("markerHeight", 6)
      .attr("orient", "auto")
      .append("path")
      .attr("fill", color)
      .attr("d", "M0,-5L10,0L0,5");
      
  const link = svg.append("g")
      .attr("fill", "none")
      .attr("stroke-width", 1.5)
      .selectAll("path")
      .data(links)
      .join("path")
      .attr("stroke", d => color(d.type))
      .attr("marker-end", d => `url(${new URL(`#arrow-${d.type}`, location)})`);

  const node = svg.append("g")
      .attr("fill", "currentColor")
      .attr("stroke-linecap", "round")
      .attr("stroke-linejoin", "round")
      .selectAll("g")
      .data(nodes)
      .join("g")
      .call(d3.drag().on("drag", dragged).on("end", dragended).on("start", dragstart));

  node.append("circle")
      .attr("stroke", "white")
      .attr("stroke-width", 1)
      .attr("r", 5)
      .style("fill", d => d.root ? "red" : "black");

  const anchor = node.append("a")
       .attr("xlink:href", d => "build-step-dependency-graph?stepId=" + d.encodedId);
  
  anchor.append("svg:text")
       .attr("x", 8)
       .attr("y", "0.31em")
       .style("fill", "#1f77b4")
       .text(d => d.simpleName);
       
  anchor.append("svg:title")
       .text(d => d.id);

  simulation.on("tick", () => {
    link.attr("d", linkArc);
    node.attr("transform", d => `translate(${d.x},${d.y})`);
  });

  |}

  {#breadcrumbs}<i class="fas fa-chevron-right fa-sm breadcrumb-separator"></i> <a href="build-steps">Build Steps</a>{/breadcrumbs}
  {#title}Build Step Dependency Graph{/title}
  {#body}
  
    <div class="row">
        <div class="col text-center">
            <span class="text-secondary h4">{currentRequest.getParam('stepId')}</span>
        </div>
    </div>
    <div class="row">
        <div class="col-md-auto">
            <ul class="list-group list-group-flush">
                <li class="list-group-item"><i class="fas fa-circle text-danger fa-sm legend-root"></i> root</li>
                <li class="list-group-item"><i class="fa fa-long-arrow-right fa-sm legend-direct-dependency"></i> direct dependencies</li>
                <li class="list-group-item"><i class="fa fa-long-arrow-right fa-sm legend-direct-dependent"></i> direct dependents</li>
                <!-- So far we only show direct dependencies and dependents -->
                <!--li class="list-group-item"><i class="fa fa-long-arrow-right fa-sm legend-dependency"></i> dependencies</li-->
            </ul>
        </div>
        <div class="col">
            <svg id="buildStepDepGraph_area" class="w-100 h-90"></svg>
        </div>
    </div>
  
  {/body}
  
  {#scriptref}
  <script src="{devRootAppend}/resources/js/d3.min.js"></script>
  {/scriptref}
{/include}
